import {arrayMethods} from './arr'
import Dep from './dep';

export function observer (data) {
    // 判断
  if (typeof data !== 'object' || data === null) {
    return data;
  }

  // 对象处理
  return new Observer(data);
}

// Object.defineProperty() 缺点：只能操作对象中的一个属性
class Observer {
  constructor (value) {
    Object.defineProperty(value, '__ob__', {
      enumerable: false,
      value: this,
      configurable: true,
      writable: true
    })

    // 要给所有的对象类型增加一个dep
    this.dep = new Dep();

    // 判断数据类型，是对象
    if (Array.isArray(value)) {
      value.__proto__ = arrayMethods

      // 处理对象数组
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

  walk (data) {
    let keys = Object.keys(data);
    for (let i = 0; i < keys.length; i ++) {
      let key = keys[i];
      let value = data[key];
      defineReactive(data, key, value);
    }
  }

  observeArray (data) {
    for (let i = 0; i < data.length; i ++) {
      observer(data[i])
    }
  }
}

function defineReactive (data, key, value) {
  // debugger
  // 深度劫持
  let childDep = observer(value);

  // 给每个属性添加一个dep
  let dep = new Dep();

  Object.defineProperty(data, key, {
    get () {
      // console.log('childDep==', childDep)

      // 收集watcher
      if (Dep.target) {
        dep.depend();
        // 收集数组dep
        if (childDep.dep) {
          childDep.dep.depend();
        }
      }
      return value;
    },
    set (newValue) {
      if (newValue === value) return;
      // 如果新的值是对象，需要递归拦截
      observer(newValue);
      value = newValue;
      dep.notify();
    },
    // configurable: true,
    // writable: true,
    // enumerable: true
  })
} 